import axios from 'axios'
import type { AxiosInstance, AxiosResponse, AxiosError } from 'axios'

/**
 * 创建axios实例
 * @param baseURL 基础URL
 * @param timeout 超时时间
 * @returns axios实例
 */
export const createAxiosInstance = (baseURL: string, timeout: number = 30000): AxiosInstance => {
  const instance = axios.create({
    baseURL,
    timeout,
    headers: {
      'Content-Type': 'application/json'
    }
  })

  return instance
}

/**
 * 处理API响应
 * @param response axios响应对象
 * @returns 处理后的响应数据
 */
export const handleApiResponse = <T>(response: AxiosResponse<T>): T => {
  if (response.status >= 200 && response.status < 300) {
    return response.data
  }
  throw new Error(`请求失败: ${response.status} ${response.statusText}`)
}

/**
 * 处理API错误
 * @param error axios错误对象
 * @returns 格式化的错误信息
 */
export const handleApiError = (error: AxiosError): string => {
  if (error.response) {
    // 服务器返回了错误状态码
    const status = error.response.status
    const data = error.response.data
    
    switch (status) {
      case 400:
        return `请求错误: ${JSON.stringify(data)}`
      case 401:
        return '未授权，请登录'
      case 403:
        return '拒绝访问'
      case 404:
        return '请求的资源不存在'
      case 408:
        return '请求超时'
      case 500:
        return '服务器内部错误'
      case 502:
        return '网关错误'
      case 503:
        return '服务不可用'
      case 504:
        return '网关超时'
      default:
        return `服务器错误: ${status}`
    }
  } else if (error.request) {
    // 请求已发送但未收到响应
    return '网络错误，请检查您的网络连接'
  } else {
    // 请求配置出错
    return `请求配置错误: ${error.message}`
  }
}

/**
 * 重试请求
 * @param request 请求函数
 * @param maxRetries 最大重试次数
 * @param delay 重试间隔（毫秒）
 * @returns Promise
 */
export const retryRequest = async <T>(
  request: () => Promise<T>,
  maxRetries: number = 3,
  delay: number = 1000
): Promise<T> => {
  let lastError: any
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await request()
    } catch (error) {
      lastError = error
      
      // 不是最后一次尝试时，等待后重试
      if (attempt < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, attempt)))
      }
    }
  }
  
  // 所有重试都失败
  throw lastError
}

/**
 * 检查网络连接状态
 * @returns Promise<boolean> 网络是否连接
 */
export const checkNetworkStatus = (): Promise<boolean> => {
  return new Promise((resolve) => {
    if (navigator.onLine) {
      // 浏览器认为在线，但可能是假阳性，进一步验证
      fetch('https://www.google.com/favicon.ico', {
        method: 'HEAD',
        cache: 'no-cache'
      })
        .then(() => resolve(true))
        .catch(() => resolve(false))
    } else {
      resolve(false)
    }
  })
}

/**
 * 防抖函数
 * @param func 要防抖的函数
 * @param wait 等待时间（毫秒）
 * @returns 防抖后的函数
 */
export const debounce = <T extends (...args: any[]) => any>(
  func: T,
  wait: number
): ((...args: Parameters<T>) => void) => {
  let timeout: NodeJS.Timeout | null = null
  
  return function(this: any, ...args: Parameters<T>) {
    const context = this
    
    if (timeout) clearTimeout(timeout)
    
    timeout = setTimeout(() => {
      func.apply(context, args)
    }, wait)
  }
}

/**
 * 节流函数
 * @param func 要节流的函数
 * @param limit 时间限制（毫秒）
 * @returns 节流后的函数
 */
export const throttle = <T extends (...args: any[]) => any>(
  func: T,
  limit: number
): ((...args: Parameters<T>) => void) => {
  let inThrottle: boolean = false
  
  return function(this: any, ...args: Parameters<T>) {
    const context = this
    
    if (!inThrottle) {
      func.apply(context, args)
      inThrottle = true
      
      setTimeout(() => {
        inThrottle = false
      }, limit)
    }
  }
}